package net.maku.events.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.github.xiaoymin.knife4j.core.util.CollectionUtils;
import lombok.AllArgsConstructor;
import net.maku.events.entity.ActivityBriskWalkEntity;
import net.maku.events.enums.*;
import net.maku.events.service.*;
import net.maku.events.vo.ActivityBaseVO;
import net.maku.events.vo.ActivityContestQuestionVO;
import net.maku.events.vo.KnowledgeAnswerQuestionVO;
import net.maku.framework.common.constant.Constant;
import net.maku.framework.common.exception.ServerException;
import net.maku.framework.common.utils.DateUtils;
import net.maku.framework.common.utils.PageResult;
import net.maku.framework.mybatis.service.impl.BaseServiceImpl;
import net.maku.events.convert.ActivityKnowledgeContestConvert;
import net.maku.events.entity.ActivityKnowledgeContestEntity;
import net.maku.events.query.ActivityKnowledgeContestQuery;
import net.maku.events.vo.ActivityKnowledgeContestVO;
import net.maku.events.dao.ActivityKnowledgeContestDao;
import net.maku.framework.security.user.SecurityUser;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 知识竞赛活动
 *
 * @author 阿沐 babamu@126.com
 * @since 1.0.0 2025-03-22
 */
@Service
@AllArgsConstructor
public class ActivityKnowledgeContestServiceImpl extends BaseServiceImpl<ActivityKnowledgeContestDao, ActivityKnowledgeContestEntity> implements ActivityKnowledgeContestService {

    private final ActivityContestQuestionService activityContestQuestionService;

    private final UserJoinActivityService userJoinActivityService;

    private final UserContestQuestionService userContestQuestionService;

    private final UserPointsRecordsService userPointsRecordsService;

    private final UserAnswerQuestionTimeService userAnswerQuestionTimeService;

    @Override
    public List<ActivityBaseVO> topActivity() {
        List<ActivityKnowledgeContestEntity> entityList = this.list(new LambdaQueryWrapper<ActivityKnowledgeContestEntity>().eq(ActivityKnowledgeContestEntity::getWhetherTop, Constant.ENABLE)
                .eq(ActivityKnowledgeContestEntity::getStatus, Constant.ENABLE));
        if (CollectionUtils.isNotEmpty(entityList)) {
            List<ActivityBaseVO> result = new ArrayList<>();
            entityList.forEach(item -> {
                ActivityBaseVO activityBaseVO = new ActivityBaseVO();
                activityBaseVO.setId(item.getId());
                activityBaseVO.setActivityTitle(item.getActivityTitle());
                activityBaseVO.setThumbnail(item.getThumbnail());
                activityBaseVO.setTopImg(item.getTopImg());
                activityBaseVO.setActivityStatus(item.getActivityStatus());
                activityBaseVO.setBusinessType(ActivityTypeEnum.KNOWLEDGE_CONTEST.getBusinessType());
                result.add(activityBaseVO);
            });
            return result;
        }
        return List.of();
    }

    @Override
    public PageResult<ActivityKnowledgeContestVO> page(ActivityKnowledgeContestQuery query) {
        IPage<ActivityKnowledgeContestEntity> page = baseMapper.selectPage(getPage(query), getWrapper(query));
        List<ActivityKnowledgeContestVO> result = BeanUtil.copyToList(page.getRecords(), ActivityKnowledgeContestVO.class);
        userJoinActivityService.getJoinActivityIdList(ActivityTypeEnum.KNOWLEDGE_CONTEST.getBusinessType(), result);
        if (CollectionUtils.isNotEmpty(result)) {
            List<Long> alreadyAnswerIdList = userContestQuestionService.getAlreadyAnswerIdList(result.stream().map(ActivityKnowledgeContestVO::getId).collect(Collectors.toList()), ActivityTypeEnum.KNOWLEDGE_CONTEST.getBusinessType());
            if (CollectionUtils.isNotEmpty(alreadyAnswerIdList)) {
                result.forEach(item -> {
                    if (alreadyAnswerIdList.contains(item.getId())) {
                        item.setAlreadyAnswer(true);
                    }
                });
            }
        }
        return new PageResult<>(result, page.getTotal());
    }

    private LambdaQueryWrapper<ActivityKnowledgeContestEntity> getWrapper(ActivityKnowledgeContestQuery query) {
        Long orgId = SecurityUser.getUser().getOrgId();
        LambdaQueryWrapper<ActivityKnowledgeContestEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ActivityKnowledgeContestEntity::getStatus, 1)
                .and(wrapper1 -> {
                    wrapper1.apply("JSON_CONTAINS(join_org_id, CAST({0} AS JSON))", orgId).or().eq(ActivityKnowledgeContestEntity::getOrgId, orgId);
                })
                .orderByDesc(ActivityKnowledgeContestEntity::getUpdateTime);
        return wrapper;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void joinActivity(Long id) {
        if (userJoinActivityService.checkJoin(ActivityTypeEnum.KNOWLEDGE_CONTEST.getBusinessType(), id)) {
            return;
        }
        ActivityKnowledgeContestEntity activityKnowledgeContestEntity = this.getById(id);
        activityKnowledgeContestEntity.setJoinCount(activityKnowledgeContestEntity.getJoinCount() + 1);
        this.updateById(activityKnowledgeContestEntity);
        userJoinActivityService.save(ActivityTypeEnum.KNOWLEDGE_CONTEST.getBusinessType(), id, activityKnowledgeContestEntity.getActivityTitle(), activityKnowledgeContestEntity.getThumbnail(), activityKnowledgeContestEntity.getActivityStartTime(), activityKnowledgeContestEntity.getActivityEndTime());
    }


    @Override
    public ActivityKnowledgeContestVO getInfoById(Long id) {
        ActivityKnowledgeContestVO activityKnowledgeContestVO = BeanUtil.copyProperties(this.getById(id), ActivityKnowledgeContestVO.class);
        activityKnowledgeContestVO.setActivityContestQuestionVOList(activityContestQuestionService.findByBusinessIdList(Collections.singletonList(id), ActivityQuestionTypeEnum.KNOWLEDGE_CONTEST.getBusinessType()));
        List<ActivityKnowledgeContestVO> result = new ArrayList<>();
        result.add(activityKnowledgeContestVO);
        userJoinActivityService.getJoinActivityIdList(ActivityTypeEnum.KNOWLEDGE_CONTEST.getBusinessType(), result);
        ActivityKnowledgeContestVO resultVo = result.get(0);
        List<Long> alreadyAnswerIdList = userContestQuestionService.getAlreadyAnswerIdList(Collections.singletonList(id), ActivityTypeEnum.KNOWLEDGE_CONTEST.getBusinessType());
        if (CollectionUtils.isNotEmpty(alreadyAnswerIdList)) {
            resultVo.setAlreadyAnswer(true);
        }
        if (!resultVo.isAlreadyAnswer()) {
            userAnswerQuestionTimeService.insertUserAnswerQuestion(id, null, UserAnswerQuestionEnum.KNOWLEDGE_CONTEST.getType());
        }
        return resultVo;
    }

    @Override
    public double answer(KnowledgeAnswerQuestionVO vo) {
        ActivityKnowledgeContestEntity entity = this.getById(vo.getKnowledgeId());
        if (ObjectUtils.isEmpty(entity)) {
            throw new ServerException("该知识竞赛活动未找到");
        }
        double points = userContestQuestionService.
                save(null, null, vo.getKnowledgeId(), ActivityQuestionTypeEnum.KNOWLEDGE_CONTEST.getBusinessType(), vo.getUserAnswerQuestionBankList());
        userPointsRecordsService.insertUserPointsRecords(vo.getKnowledgeId(), ActivityTypeEnum.KNOWLEDGE_CONTEST.getBusinessType(), points, WhetherAddEnum.ADD.getType());
        userAnswerQuestionTimeService.completedUserAnswerQuestion(vo.getKnowledgeId(), null, UserAnswerQuestionEnum.KNOWLEDGE_CONTEST.getType());
        return points;
    }


    @Scheduled(cron = "0 0/10 * * * ? ")
    @Transactional(rollbackFor = Exception.class)
    public void updateActivityEndStatus() {
        List<ActivityKnowledgeContestEntity> entityList = this.list(new LambdaQueryWrapper<ActivityKnowledgeContestEntity>().eq(ActivityKnowledgeContestEntity::getActivityStatus, ActivityStatusEnum.BEGIN.getStatus())
                .apply("date_format(activity_end_time,'%Y-%m-%d %H:%i:%s') < date_format ({0},'%Y-%m-%d %H:%i:%s')", DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN)));
        if (CollectionUtils.isNotEmpty(entityList)) {
            entityList.forEach(item -> {
                item.setActivityStatus(ActivityStatusEnum.END.getStatus());
            });
            this.saveOrUpdateBatch(entityList);
        }
        List<ActivityKnowledgeContestEntity> notStartList = this.list(new LambdaQueryWrapper<ActivityKnowledgeContestEntity>().eq(ActivityKnowledgeContestEntity::getActivityStatus, ActivityStatusEnum.NOT_START.getStatus())
                .apply("date_format(activity_start_time,'%Y-%m-%d %H:%i:%s') < date_format ({0},'%Y-%m-%d %H:%i:%s')", DateUtils.format(new Date(), DateUtils.DATE_TIME_PATTERN)));
        if (CollectionUtils.isNotEmpty(notStartList)) {
            notStartList.forEach(item -> {
                item.setActivityStatus(ActivityStatusEnum.BEGIN.getStatus());
            });
            this.saveOrUpdateBatch(notStartList);
        }
    }

}